最近在工作上,有个同事向我请教问题,把我问住了,我只是个刚毕业的应届生。
由我编写的后端中,Web 服务器是由 Flask 驱动的,而它需要一个 WSGI 服务器来驱动。后端需要存储在终端本地,且由于需要与本地的多个硬件交互,如摄像头、麦克风,必须开启 https。又由于新终端要从旧终端迁移,有些接口是旧的,请求的端口和 uWSGI 默认的端口还不一致,还不支持 https,于是我还要做一个端口转发。本来这些活应该是运维的活……
问题是,我们既然需要使用 https 通信,我们就需要申请证书。本地或局域网通信,使用自签名证书即可,但终端几百台,遍布北京各地,我们需要每个终端各申请一部证书吗。我们有些业务使用 Java 编写后端,且托管在公网域名,它的证书已经配置好了,这种证书和我们的自签名证书又有何区别。Nginx配置,证书文件,这些都是什么,我当时没答上来。
以前的计算机网络原理课我就没听。对于证书,我也是只知道怎么给自己的网站配,我又不是搞运维的。他这么一问,我自己私下翻阅文档,询问 ChatGPT,也算是搞懂了它内部的原理。
我们看网页,网页的协议是 https,就是从 http 加密过来的,这其中的加密套件叫 “TLS”。在 TCP/IP 四层模型中,http 协议位于应用层,基于 TCP 协议,TCP 协议位于传输层。TLS 位于 TCP 之上,为应用层协议提供加密支持,除了我们熟知的 http,还有 websocket、FTP、IMAP、SMTP等。目前 TLS 已经发展到了 1.3 版本,我在涉及到选择 TLS 加密版本的选项的时候,都会选择 TLS 1.2 和 TLS 1.3。
TLS 协议的加密原理大致是:
- 客户端发起握手,发送支持的加密套件列表等信息;
- 服务器返回证书、公钥等信息;
- 客户端验证服务器身份,生成对称密钥(通过公钥加密传输);
- 双方协商出一个对称密钥后,用它加密后续通信。
我们在自己网站上部署的都是公网证书,由 CA 机构颁发,浏览器默认信任。自签名证书由自己签发自己认证,在没有安装根证书的前提下,本地设备是不认可服务器的身份的。
公网证书分三级,依次是 DV、OV、DV 证书,越来越严格。
证书有它自己的证书链,最底层的是根证书,由权威 CA 签发,预装在操作系统或浏览器中,安全等级最高。下一层为中间证书,由根证书签发,它可以存在多级,需要拼接起来。最后是服务器证书,安装在我们的服务器中,包括公钥、域名、有效期等信息。
自签名证书的根证书则是我们自己创建,需要我们自己安装到操作系统上,且它可以签发服务器证书。
在签发证书的过程中,我们可能会遇到以下几种文件:
- 私钥文件:用于生成证书请求和后续解密通信,必须保密,通常扩展名 .key。
- 证书签名请求文件(CSR):包含申请证书的主体信息和公钥,由私钥生成,提交给 CA 签发,通常扩展名 .csr。
- 根证书:最高级的信任证书,由根 CA 生成并受操作系统或浏览器信任,扩展名常为 .pem、.crt。
- 中间证书:根证书签发的中间 CA 证书,用来签发服务器证书,连接根证书和服务器证书,通常是 .pem、.crt。
- 服务器证书:签发给服务器的证书,包含服务器公钥和身份信息,扩展名通常 .crt、.pem。
- 证书链文件:把服务器证书和中间证书合并,用于配置服务器时提供完整信任链。
了解以上知识之后,我们就可以先本地签发一个根证书,用它给所有终端批量签发证书,终端只需导入根 CA 证书信任列表即可。每个终端可能会有自己的域名,那就可以本地签发一个通配符证书,方便管理。
顺带一提,这个问我的人是个组长,他们的项目拖了三个月,这几天正在加班。